home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Src / cont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  5.1 KB  |  203 lines

  1. /*
  2.  *
  3.  * c o n t . c                -- Continuations management
  4.  *
  5.  * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
  6.  * 
  7.  *
  8.  * Permission to use, copy, and/or distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that both the above copyright notice and this permission notice appear in
  11.  * all copies and derived works.  Fees for distribution or use of this
  12.  * software or derived works may only be charged with express written
  13.  * permission of the copyright holder.  
  14.  * This software is provided ``as is'' without express or implied warranty.
  15.  *
  16.  * This software is a derivative work of other copyrighted softwares; the
  17.  * copyright notices of these softwares are placed in the file COPYRIGHTS
  18.  *
  19.  *
  20.  *           Author: Erick Gallesio [eg@kaolin.unice.fr]
  21.  *    Creation date:  8-Nov-1993 11:34
  22.  * Last file update: 26-Apr-1996 17:46
  23.  */
  24.  
  25. #include "stk.h"
  26. #include "gc.h"
  27.  
  28. #ifdef sparc
  29. #define FLUSH_REGISTERS_WINDOW()    asm("t 0x3") /* Stolen in Elk 2.0 source */
  30. #else
  31. #define FLUSH_REGISTERS_WINDOW()
  32. #endif
  33.  
  34. struct cont {
  35.   jmp_buf env;
  36.   SCM wind_stack;
  37.   SCM *start;
  38.   unsigned length;
  39.   SCM stack[1];
  40. };
  41.  
  42. #define C_ENV(x)     (((struct cont *)((x)->storage_as.cont.data))->env)
  43. #define C_START(x)    (((struct cont *)((x)->storage_as.cont.data))->start)
  44. #define C_LEN(x)    (((struct cont *)((x)->storage_as.cont.data))->length)
  45. #define C_STACK(x)    (((struct cont *)((x)->storage_as.cont.data))->stack)
  46. #define C_WIND_STACK(x)    (((struct cont *)((x)->storage_as.cont.data))->wind_stack)
  47.  
  48.  
  49. static SCM call_cc_escaped_value;
  50.  
  51. /* Don't allocate these vars on stack */
  52. static SCM *from, *to;
  53. static long length;
  54. static int  i;
  55.  
  56.  
  57. static void unwind(SCM stop, int n);
  58.  
  59. static int get_stack_length(void)
  60. {
  61.   SCM stack_limit;
  62.   
  63.   return (&stack_limit < STk_stack_start_ptr) ? STk_stack_start_ptr - &stack_limit
  64.                               : &stack_limit - STk_stack_start_ptr;
  65. }
  66.  
  67. static SCM prepare_call_cc(SCM proc)
  68. {
  69.   SCM z;
  70.  
  71.   if (STk_procedurep(proc) == Ntruth)
  72.     Err("call-with-current-continuation: Bad procedure", proc);
  73.  
  74.   /* Find the start adress and the length of the stack to save */
  75.   length = get_stack_length();
  76.   from   = (STk_stack_start_ptr<&z) ? STk_stack_start_ptr 
  77.                     : STk_stack_start_ptr-length;
  78.  
  79.   /* Allocate a new object for this continuation */
  80.   NEWCELL(z, tc_cont);
  81.  
  82.   z->storage_as.cont.data = must_malloc(sizeof(struct cont) + length * sizeof(SCM));
  83.  
  84.   C_START(z)       = from;
  85.   C_LEN(z)         = length;
  86.   C_WIND_STACK(z) = STk_wind_stack;
  87.   FLUSH_REGISTERS_WINDOW();
  88.   for (i=length, to = C_STACK(z); i--; ) *to++ = *from++;
  89.  
  90.   return z;
  91. }
  92.  
  93. SCM STk_mark_continuation(SCM cont)
  94. {
  95.   STk_mark_stack((SCM *)C_STACK(cont), (SCM *)(C_STACK(cont)+C_LEN(cont)-1));
  96.   return C_WIND_STACK(cont);
  97. }
  98.  
  99. SCM STk_do_call_cc(SCM *x)
  100. {
  101.   SCM tmp;
  102.   
  103.   tmp = prepare_call_cc(*x);
  104.   /* Use a setjmp/longjmp for the continuation */
  105.   if (setjmp(C_ENV(tmp)) == 0) {
  106.     *x = LIST2(*x, tmp);
  107.     return Truth;
  108.   }
  109.   else
  110.     return (*x=call_cc_escaped_value);
  111. }
  112.  
  113. void STk_throw(SCM fct, SCM val)
  114. {
  115.   static SCM tmp;
  116.   union {
  117.     SCM stack_end;
  118.     SCM hole[1024]; /* Reserve 1K-pointers on stack */
  119.   }u;
  120.  
  121.   /* Evaluate room on stack. If not enough call throw again to alloc. a new hole */
  122.   if (&u.stack_end < STk_stack_start_ptr) {
  123.     /* Stack grows downward */
  124.     if (&u.stack_end > C_START(fct)) STk_throw(fct, val);
  125.   }
  126.   else {
  127.     /* Stack grows upward */
  128.     if (&u.stack_end < C_START(fct)+ C_LEN(fct)) STk_throw(fct, val);
  129.   }
  130.  
  131.   /* Take care of active dynamic-winds */
  132.   tmp = C_WIND_STACK(fct);
  133.   unwind(tmp, STk_llength(STk_wind_stack) - STk_llength(tmp));
  134.  
  135.   /* Save val in a global and reset stack as it was before calling call/cc */
  136.   call_cc_escaped_value = val; tmp = fct;
  137.   FLUSH_REGISTERS_WINDOW();
  138.   for(to=C_START(fct), from=C_STACK(fct), i=C_LEN(fct); i--; ) *to++ = *from++;
  139.  
  140.   /* And Go! */
  141.   longjmp(C_ENV(tmp), JMP_THROW);
  142. }
  143.  
  144. PRIMITIVE STk_continuationp(SCM obj)
  145. {
  146.   return CONTINUATIONP(obj)? Truth: Ntruth;
  147. }
  148.  
  149. /******************************************************************************
  150.  *
  151.  * Dynamic wind 
  152.  *
  153.  ******************************************************************************/
  154.  
  155. void STk_unwind_all(void)
  156. {
  157.   SCM p;
  158.  
  159.   for (p = STk_wind_stack; NNULLP(p); p = CDR(p)) {
  160.     STk_wind_stack = CDR(p);
  161.     Apply(CAR(CDR(CAR(p))), NIL);
  162.   }
  163. }
  164.  
  165. static void unwind(SCM stop, int n)
  166. {
  167.   if (STk_wind_stack != stop) {
  168.     if (n < 0) {
  169.       unwind(CDR(stop),n+1);
  170.       Apply(CAR(CAR(stop)),NIL);
  171.       STk_wind_stack = stop;
  172.     }
  173.     else {
  174.       SCM old_wind_stack = STk_wind_stack;
  175.       
  176.       STk_wind_stack = CDR(STk_wind_stack);
  177.       Apply(CAR(CDR(CAR(old_wind_stack))), NIL);
  178.       unwind(stop, n-1);
  179.     }
  180.   }
  181. }
  182.  
  183. static void test_procedure(SCM thunk)
  184. {
  185.   if (!STk_is_thunk(thunk)) Err("dynamic-wind: bad procedure", thunk);
  186. }
  187.  
  188. PRIMITIVE STk_dynamic_wind(SCM thunk1, SCM thunk2, SCM thunk3)
  189. {
  190.   SCM result;
  191.  
  192.   test_procedure(thunk1);
  193.   test_procedure(thunk2);
  194.   test_procedure(thunk3);
  195.  
  196.   Apply(thunk1, NIL);
  197.   STk_wind_stack = Cons(LIST2(thunk1, thunk3), STk_wind_stack);
  198.   result = Apply(thunk2, NIL);
  199.   STk_wind_stack = CDR(STk_wind_stack);
  200.   Apply(thunk3, NIL);
  201.   return result;
  202. }
  203.